import { ETaskState } from "GameLoop/DecisionMaking/TaskDeclare/type";
import { ATaskAdapter } from ".";
import { getRoleConfig } from "utils/constants/bodyconstant";
import { TaskHelper } from "utils/task/TaskHelper";
import { spawnPriority } from "utils/constants/priorityconstant";
import { CreepTaskChecker } from "../TaskCheck/CreepTaskChecker";
import { StationNetwork } from "GameLoop/Path/StationNetwork";


/*@profile*/
export class CreepTaskAdapter extends ATaskAdapter<"creep">
{
    constructor(context:IContextGetter,world:WorldGetter)
    {
        super(context,world);
        CreepTaskChecker.notify = this.notify.bind(this);
    }
 
    public bindTasks(room: Room, creeptasks: ITaskDeclare["creep"][],customCheck:IConditionFunction): void 
    {
        const creepRecord = room.getIdleCreeps();
        const creeplimit = this.getCreepLimit(room);
        for(const task of creeptasks)
        {
              // 对任务进行分类整理
            const taskcreeps = task.data.creeps;
            for(let i=0;i<taskcreeps.length;)
            {
                let name  =   taskcreeps[i];
                if(!Game.creeps[name]  )
                {
                    task.data.creeps.splice(i,1);
                }
                else 
                {
                    i++;
                } 
            }
            const code = customCheck(room as Required<Room>,task)
            if(code == ETaskState.Complete )
            {
                room.deleteTaskById(task.id,"creep");
                continue;
            }
            else if(code == ETaskState.Pause)
            {
                 
                // 释放已有的爬
                taskcreeps.forEach(e=>
                    {
                        Game.creeps[e].memory.taskid=undefined;
                        Game.creeps[e].ownerRoom().addCreep(e,Game.creeps[e].ActiveRole());

                    });
                task.data.creeps=[];

                continue;
            }
            if(ETaskState.Complete == this.checkState(room,task))
            {
                room.deleteTaskById(task.id,"creep");
                continue;
            }
            if(!task.data.cost  )
            {
                task.data.cost = TaskHelper.getTaskPathCost(room.name,task.data.room)
            }
            this.bindTask(room as Required< Room>,task,creepRecord);
            if(!task.data.disableSpawn)
            {
                this.postSpawnTask(room as Required< Room>,task )
            }
           
        }
        this.postSpawnRole(room as Required< Room>,"filler", creeplimit)
        if(room.terminal)
        {
            this.postSpawnRole(room as Required< Room>,"manager", creeplimit)
        }
    }
 /**
     * 因为任务会绑定很多个爬,所以在爬的执行内检查就会导致重复运算.
     * 所以只能另外单独检查任务是否完成。以及任务的属性更新
     * // 目前只检查任务是否完成。和属性。  暂时不检查任务是否暂停
     * */ 
    protected checkState(room:Room,task:ITaskDeclare["creep"]):ETaskState
    {
        return CreepTaskChecker.check(room,task);
    }

 
    /**
     * 获取本房间的孵化数量限制。剩余可孵化角色的数量
     * @param room 
     * @returns 
     */
     private getCreepLimit(room:Room):Readonly<Record<string, number>>
     {
         const keepTask = room.getTaskByType("KeepCreep")[0];
         if(!keepTask)
         {
            room.log("warn",'KeepCreep任务未初始化!')
            return {};
         }
         const creep_limit:Record<string,number>={} as any;
        
         for(const e of keepTask.data.role)
         {
             creep_limit[e[0].Role]=  e[1]
         }
         return creep_limit;
     }

    private postSpawnRole( room:Required< Room>,role:RoleName, creepLimit:Record<string,number>)
    {
        const spawn = room.getEntity("SpawnEntity");
        const limit = creepLimit[role];
        const spawned = spawn.getSpawnCountByRole(role);
        const exist = room.memory.roleStatus[role]?room.memory.roleStatus[role].length:0;
        if(limit<=spawned+exist)
        {
            return;
        }
        const configs:[IBodyConfig,number][]=[]
        {
            const bodyconfig =  getRoleConfig(role,room.controller.level);
            configs.push([{Role:role,body :bodyconfig.body,isAdapt:true},limit- (spawned+exist)]);
            if(configs[0][1]>0)
            {
                const spawntask = TaskHelper.getSpawnGroupTask(spawn.GUID(),configs,spawnPriority[role]);
                spawn.addTask(spawntask);
            }
        }
         
    }

 
    /**
     * 多退少补
     * @param task 
     * @param creep 
     */
    private bindTask(room:Required< Room>,task:ITaskDeclare["creep"],creep:Record<RoleName,Creep[]>)
    {

        const bindCreep=(task:ITaskDeclare["creep"],creep:Creep)=>
        {
            task.data.creeps.push(creep.name)
            creep.memory.taskid = task.id;
            room.removeIdleCreep(creep);
        }
 
        const existvalidCreeps:Record<RoleName,Creep[]>= this.getValidCreeps(room,task);

        for(const req of task.data.required)
        {
            let sum = 0;
            for(const r of req[0])
            {
                sum+=existvalidCreeps[r]?existvalidCreeps[r].length:0;
            }
            if(sum< req[1])
            {
                // 不足
                for(let i=sum ;i<req[1];i++)
                {
                    for(const e of req[0])
                    {
                        if(creep[e]?.length )
                        {
                            bindCreep(task,creep[e].pop() as Creep);
                        }
                    }
                }
            }
            
        }

    }
  
    // 检测
    /**
     * 
     * @param room 
     * @param task 
     * @param role 
     * @param creepLimit role的数量限制
     * @param needcount 需要的数量, required 减去已经有的
     */
    private postSpawnTask(room:Required< Room>,task:ITaskDeclare["creep"] )
    {
        const spawnentity = room.getEntity("SpawnEntity");
        
        const validcreeps = this.getValidCreeps(room,task);
       
       //  const spawnRecord:Record<RoleName,number>={} as any;
        const configs:[IBodyConfig,number][]=[];
        const spawntask = spawnentity.getTasksByOwner(task.id);
        for(const e of task.data.required)
        {
            const role =  e[0][0];
            const existnum = _.sum(e[0],n=> validcreeps[n]?validcreeps[n].length:0);
            // 本任务已经达标了
            const spawnNum =  _.sum(e[0],n=>spawnentity.getSpawnCountByRole(n,task.id)); 
           
            const tasklimit = e[1]- (spawnNum+existnum);
            // global.Log.Info(` 角色:${JSON.stringify(e[0])} 需求:${e[1]} 正在孵化:${ spawnNum}   已有:${existnum}  可孵化数量:${tasklimit}`);
            const bodyconfig =  this.getSpawnRoleConfig(role,room,task);
            if(!bodyconfig)
            {
                spawnentity.log("warn",`找不到${role}的body配置`);
            }
            if(tasklimit<=0 )
            {
                // spawnRecord[role]=0;
                // continue;
                // configs.push([{Role:role,body :bodyconfig.body,isAdapt:true},0])
                if(tasklimit<0&& spawntask)
                {
                    const idx = spawntask.data.spawn_info.findIndex(e=>e.bodyconfig.Role == role);
                    if(idx>-1)
                    {
                        if(existnum>=e[1])
                        {
                            // 已经达标了
                            spawntask.data.spawn_info[idx].count=0;
                        }
                        else 
                        {
                            spawntask.data.spawn_info[idx].count =e[1]-existnum;
                        }
                    }
                }
                
            }
            else 
            {
                configs.push([{Role:role,body :bodyconfig.body,isAdapt:true},tasklimit])
            }
            // spawnRecord[role] = tasklimit;
        }
       
        if(!spawntask)
        {
            const spawntask = TaskHelper.getSpawnGroupTask(task.id,configs,task.priority);
            spawnentity.addTask(spawntask);
        }

         
    }
    private getValidCreeps(room:Required< Room>,task:ITaskDeclare["creep"])
    {
        const existvalidCreeps:Record<RoleName,Creep[]>={} as any;
        const freeCreeps:Creep[]=[];
        for(const e of task.data.creeps)
        {
            const creep = Game.creeps[e];
            if(!creep || (creep && creep.ticksToLive && creep.ticksToLive<task.data.cost+creep.body.length))
            {
                // 所有porter类的角色。低于路程就要释放掉。免得运输到一半挂了
                if(creep&& creep.ActiveRole() == 'porter' && creep.store.getUsedCapacity() ==0)
                {
                    // 释放
                    freeCreeps.push(creep);
                    
                }
                continue;
            }
            if(existvalidCreeps[creep.memory.Role])
            {
                existvalidCreeps[creep.memory.Role].push(creep)
            }
            else
            {
                existvalidCreeps[creep.memory.Role]= [creep]
            }
            
        }
        room.freeTaskCreeps(task,freeCreeps);
        return existvalidCreeps
    }

    //
    private getSpawnRoleConfig(role:RoleName,room:Required<Room>,task:ITaskDeclare["creep"])
    {
        if(task.data.bodyconfig)
        {
            const bodyconfig = task.data.bodyconfig.find(e=>e.Role ==role);
            if(bodyconfig)
            {
                return bodyconfig
            }
        }
        return getRoleConfig(role,room.controller.level);
    }
}